package com.zmh.wt.healthmonitor.utils;

import com.zmh.wt.healthmonitor.constant.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;

//20201223测试通过，可以转换大文件
public class Txt2WavUtil {
    //采样率44100 * 8s长度的音频文件
    static Logger logger = LoggerFactory.getLogger(Txt2WavUtil.class);

    private static final int DataLength = 44100 * 8;

    public static void main(String[] args) throws IOException {
        File file = new File("/home/zhangben/Desktop/txt2wavtest/BladeTest2.txt");
        String readPath = "E:\\txt测试数据\\A01-20190722131913.txt";
        String savePath = "D:\\FtpCenter\\";

        toWavFile(readPath, savePath, "wavtest");
    }

    /**
     * txt转wav
     *
     * @param readPath 读取路径
     * @param savePath 存储路径
     * @param wavname  存储文件名（不包括wav后缀）
     * @throws IOException
     */
    public static void toWavFile(String readPath, String savePath, String wavname) throws IOException {
        File file = new File(readPath);

        //crate TxtConvertResults folder to save wav file
//        logger.info("This is txt2wav mul file");
        File filedir = new File(savePath);
        if (!filedir.exists() && !filedir.isDirectory()) {
//            logger.info("txt2wav: file not exit and creat");
            filedir.mkdir();
        } else {
//            logger.info("txt2wav: dir alread exit!");
        }

        //empty the 'TxtfileConvertResults' folder
//        File[] fs = filedir.listFiles();
//        for(File f:fs){
//            f.delete();
//        }

        //txt to wav
        //统计文件的行数,计算文件的长度,并且找到最大值和最小值的绝对值
        double min = 0.0;
        double max = 0.0;
        double absmax = 0.0;
        BufferedReader reader = null;
        int line = 0;
        try {
            System.out.println("txt2wav: begin to read file " + file.getName());
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
//            int line = 0;
            // 一次读入一行，直到读入null为文件结束
            List<Double> buffer = new ArrayList<Double>();
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                //buffer.add(Double.parseDouble(tempString.trim()));
                double temp = Double.parseDouble(tempString.trim());
                max = Math.max(temp, max);
                min = Math.min(temp, min);
                line++;
            }
            System.out.println("txt2wav: line " + line);
            absmax = Math.max(Math.abs(max), Math.abs(min));
            System.out.println("txt2wav: absmax" + absmax);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }

        int DataLength = line;
        //add relative path
        //there need a new input to set wavname which is getted from searching txtfile
        File wavpath = new File(savePath + "\\" + wavname + ".wav");
        FileOutputStream out = new FileOutputStream(wavpath);

        out.write("RIFF".getBytes());
        // DataLength + 36 数据的长度 + 除了前两个之后的头文件长度
        out.write(intToByteArraySmall(DataLength + 36));
        out.write("WAVE".getBytes());
        out.write("fmt".getBytes());
        out.write(0x20);
        out.write(intToByteArraySmall(16));
        out.write(shortToByteArraySmall((short) 1));
        out.write(shortToByteArraySmall((short) 1));
        out.write(intToByteArraySmall(44100));
        out.write(intToByteArraySmall(44100));
        out.write(shortToByteArraySmall((short) 1));
        out.write(shortToByteArraySmall((short) 8));
        out.write("data".getBytes());
        out.write(intToByteArraySmall(DataLength));
//        Random r = new Random(1);
//        for(int i = 0; i < DataLength; i++){
//            out.write(r.nextInt(65535));
//        }

        System.out.println("txt2wav: 文件创建成功！");
        //开始进行数据转换
        line = 0;
        try {
            System.out.println("txt2wav: begin to read file" + file.getName());
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
//            int line = 0;
            // 一次读入一行，直到读入null为文件结束
//            List<Double> buffer = new ArrayList<Double>();
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                //buffer.add(Double.parseDouble(tempString.trim()));
//                System.out.println(tempString);
                line++;
                double temp = Double.parseDouble(tempString);
                int maxmintrans = (int) ((temp / absmax) * 128) + 128;
                out.write(maxmintrans);
            }
            System.out.println(line);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                    out.close();
                } catch (IOException e1) {
                }
            }
        }
    }

    /**
     * 数组转wav文件
     *
     * @param txtData
     * @param wavName
     * @param max
     * @param min
     * @return
     * @throws IOException
     */
    public static Integer doubleDataToWavFile(Double[] txtData, String wavName, Double max, Double min) throws IOException {


        //存储路径
        File filedir = new File(".\\wavFile");
        if (!filedir.exists() && !filedir.isDirectory()) {
            filedir.mkdir();
        }

        int DataLength = txtData.length;
        //add relative path
        String relativePath = ".\\wavFile" + "\\" + wavName + ".wav";
        File wavpath = new File(relativePath);
        FileOutputStream out = new FileOutputStream(wavpath);

        out.write("RIFF".getBytes());
        // DataLength + 36 数据的长度 + 除了前两个之后的头文件长度
        out.write(intToByteArraySmall(DataLength + 36));
        out.write("WAVE".getBytes());
        out.write("fmt".getBytes());
        out.write(0x20);
        out.write(intToByteArraySmall(16));
        out.write(shortToByteArraySmall((short) 1));
        out.write(shortToByteArraySmall((short) 1));
        out.write(intToByteArraySmall(44100));
        out.write(intToByteArraySmall(44100));
        out.write(shortToByteArraySmall((short) 1));
        out.write(shortToByteArraySmall((short) 8));
        out.write("data".getBytes());
        out.write(intToByteArraySmall(DataLength));

        logger.info("txt2wav: 文件创建成功！文件相对路径:{}", relativePath);
        //开始进行数据转换
        Double absmax = Math.max(Math.abs(max), Math.abs(min));
        try {
            // 一次读入一行，直到读入null为文件结束
//            List<Double> buffer = new ArrayList<Double>();
            for (int i = 0; i < txtData.length; i++) {
                // 显示行号
                double temp = txtData[i];
                int maxmintrans = (int) ((temp / absmax) * 128) + 128;
                out.write(maxmintrans);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return Constants.FAIL_INT;
        }

        return Constants.SUCCESS_INT;
    }

    //将int转换为长度为4的字节数组，大端，在这个demo里面没用到这个函数
    public static byte[] intToByteArrayBig(int i) {
        byte[] result = new byte[4];
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    //将int转换为长度为4的字节数组，小端。
    public static byte[] intToByteArraySmall(int i) {
        byte[] result = new byte[4];
        result[3] = (byte) ((i >> 24) & 0xFF);
        result[2] = (byte) ((i >> 16) & 0xFF);
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    //将Short转换为长度为2的字节数组，小端。
    public static byte[] shortToByteArraySmall(short i) {
        byte[] result = new byte[2];
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }
}
